Many commercial finite element codes provide an interface that allows users to implement general material constitutive equations. A user material model:
is used to define the mechanical constitutive behavior of a material;
is called at integration points of elements for which the material definition includes a user-defined material behavior;
can use solution-dependent state variables;
updates the stresses and solution-dependent state variables to their values at the end of the increment for which it is called;
for most implicit solvers must provide the material Jacobian matrix, $\partial\Delta\pmb{\sigma}/\partial\Delta\pmb{\epsilon}$;
Use the user material interface only when none of the existing material models included in the code's material library accurately represents the behavior of the material to be modeled.
Requires one of the following:
It is also likely to require:
Use a suitable integration procedure (this is the hard part!):
Forward Euler (explicit integration)
Simple to implement, but has a stability limit
$$\Delta\epsilon < \Delta\epsilon_{\rm stab}$$
where $\Delta\epsilon_{\rm stab}$ is usually less than the elastic strain magnitude.
Backward Euler (implicit integration)
Midpoint method
For small-deformation problems (e.g., linear elasticity) or large-deformation problems with small volume changes (e.g., metal plasticity), the consistent Jacobian is
$$ \mathbb{C} = \frac{\partial\Delta\pmb{\sigma}}{\partial\Delta\pmb{\epsilon}}$$
where $\Delta\sigma$ is the increment in stress and $\Delta\epsilon$ is the increment in strain.
If large deformations with large volume changes are considered (e.g., pressure-dependent plasticity), the exact form of the consistent Jacobian
$$ \mathbb{C} = \frac{1}{J}\frac{\partial\Delta\left(J\pmb{\sigma}\right)}{\partial\Delta\pmb{\epsilon}}$$
should be used to ensure rapid convergence.
For hyperelastic constitutive equations, in which $\pmb{\sigma}$ is a proper function of the deformation, the consistent Jacobian is defined by:
$$\delta\left(J\pmb{\sigma}\right) = J\mathbb{C}{:}\delta\pmb{d}$$
∗DEPVAR
option.In Abaqus, run tests with all displacements prescribed to verify the integration algorithm for stresses and state variables.
Suggested tests include:
Run similar tests with load prescribed to verify the accuracy of the Jacobian.
sqa_stiff
option to compare stiffness to that computed numericallySUBROUTINE UMAT(STRESS, STATEV, DDSDDE, SSE, SPD, SCD, RPL,
1 DDSDDT, DRPLDE,DRPLDT,STRAN,DSTRAN,TIME,DTIME,TEMP,DTEMP,
2 PREDEF,DPRED, CMNAME, NDI, NSHR, NTENS, NSTATV, PROPS, NPROPS,
3 COORDS, DROT, PNEWDT, CELENT, DFGRD0, DFGRD1, NOEL, NPT, LAYER,
4 KSPT, KSTEP, KINC)
INCLUDE 'ABA_PARAM.INC'
CHARACTER*8 CMNAME
DIMENSION STRESS(NTENS), STATEV(NSTATV), DDSDDE(NTENS, NTENS),
1 DDSDDT(NTENS), DRPLDE(NTENS), STRAN(NTENS), DSTRAN(NTENS),
2 PREDEF(1), DPRED(1), PROPS(NPROPS), COORDS(3), DROT(3, 3),
3 DFGRD0(3, 3), DFGRD1(3, 3)
implicit none
is used, make sure the precision set matches that of AbaqusThe following quantities are available in UMAT:
The following quantities must be defined:
The following variables may be defined:
A complete description of all parameters is given in the Abaqus user subroutines guide
SINV
will return the first and second invariants of a tensor.SPRINC
will return the principal values of a tensor.SPRIND
will return the principal values and directions of a tensor.ROTSIG
will rotate a tensor with an orientation matrix.XIT
will terminate an analysis and close all files associated with the analysis properly.STD_ABQERR
sends messages to Abaqus to write to output filesFor more details, see the Abaqus user subroutines guide
Sresses and strains are stored as vectors
The shear strain is stored as engineering shear strain
$$\gamma_{ij} = 2\epsilon_{ij}, \quad i\ne j$$The deformation gradient, $F_{ij}$, is always stored as a three-dimensional matrix
For geometrically nonlinear analysis the strain increment and incremental rotation passed into the routine are based on the Hughes-Winget formulae.
The user must define the Cauchy stress: when this stress reappears during the next increment, it will have been rotated with the incremental rotation, DROT
, passed into the subroutine.
ROTSIG
if this is not desired.If the ∗Orientation
option is used in conjunction with UMAT, stress and strain components will be in the local system (again, this basis system rotates with the material in finite-strain analysis).
Tensor state variables must be rotated in the subroutine (use ROTSIG
).
At the start of a new increment, the strain increment is extrapolated from the previous increment.
∗STEP, EXTRAPOLATION=NO
If the strain increment is too large, the variable PNEWDT
can be used to suggest a reduced time increment.
PNEWDT*DTIME.
The characteristic element length can be used to define softening behavior based on fracture energy concepts.
Constitutive law:
$$\pmb{\sigma} = 3K{\rm iso}\pmb{\epsilon} + 2G{\rm dev}\pmb{\epsilon}$$
Jaumann (corotational) rate form:
$$\dot{\pmb{\sigma}} = 3K{\rm iso}\dot{\pmb{\epsilon}} + 2G{\rm dev}\dot{\pmb{\epsilon}}$$
The Jaumann rate equation is integrated in a corotational framework:
The appropriate coding is shown in the following cells.
subroutine umat(stress, statev, ddsdde, sse, spd, scd, rpl, &
ddsddt, drplde, drpldt, stran, dstran, time, dtime, temp, dtemp, &
predef, dpred, cmname, ndi, nshr, ntens, nstatv, props, nprops, &
coords, drot, pnewdt, celent, dfgrd0, dfgrd1, noel, npt, layer, &
kspt, kstep, kinc)
implicit none
character*8, intent(in) :: cmname
integer, intent(in) :: ndi, nshr, ntens, nstatv, nprops
integer, intent(in) :: noel, npt, layer, kspt, kstep, kinc
real(8), intent(in) :: sse, spd, scd, rpl, drpldt, time, dtime, temp, dtemp
real(8), intent(in) :: pnewdt, celent
real(8), intent(inout) :: stress(ntens), statev(nstatv), ddsdde(ntens, ntens)
real(8), intent(inout) :: ddsddt(ntens), drplde(ntens)
real(8), intent(in) :: stran(ntens), dstran(ntens)
real(8), intent(in) :: predef(1), dpred(1), props(nprops), coords(3)
real(8), intent(in) :: drot(3, 3), dfgrd0(3, 3), dfgrd1(3, 3)
integer :: i, j
real(8) :: K, K3, G, G2, Lam
character*120 :: msg
character*8 :: charv(1)
integer :: intv(1)
real(8) :: realv(1)
! ------------------------------------------------------------------------- !
implicit none
usedif (ndi /= 3) then
msg = 'this umat may only be used for elements &
&with three direct stress components'
call stdb_abqerr(-3, msg, intv, realv, charv)
end if
! elastic properties
K = props(1)
K3 = 3. * K
G = props(2)
G2 = 2. * G
Lam = (K3 - G2) / 3.
! elastic stiffness
ddsdde = 0.
do i=1,ndi
do j = 1,ndi
ddsdde(j,i) = Lam
end do
ddsdde(i,i) = G2 + Lam
end do
do i=ndi+1,ntens
ddsdde(i,i) = G
end do
! stress update
stress = stress + matmul(ddsdde, dstran)
return
end subroutine umat
In [1]:
from matmodlab2 import *
In [2]:
%%writefile umat_elastic.f90
subroutine umat(stress, statev, ddsdde, sse, spd, scd, rpl, &
ddsddt, drplde, drpldt, stran, dstran, time, dtime, temp, dtemp, &
predef, dpred, cmname, ndi, nshr, ntens, nstatv, props, nprops, &
coords, drot, pnewdt, celent, dfgrd0, dfgrd1, noel, npt, layer, &
kspt, kstep, kinc)
implicit none
character*8, intent(in) :: cmname
integer, intent(in) :: ndi, nshr, ntens, nstatv, nprops
integer, intent(in) :: noel, npt, layer, kspt, kstep, kinc
real(8), intent(in) :: sse, spd, scd, rpl, drpldt, time, dtime, temp, dtemp
real(8), intent(in) :: pnewdt, celent
real(8), intent(inout) :: stress(ntens), statev(nstatv), ddsdde(ntens, ntens)
real(8), intent(inout) :: ddsddt(ntens), drplde(ntens)
real(8), intent(in) :: stran(ntens), dstran(ntens)
real(8), intent(in) :: predef(1), dpred(1), props(nprops), coords(3)
real(8), intent(in) :: drot(3, 3), dfgrd0(3, 3), dfgrd1(3, 3)
integer :: i, j
real(8) :: K, K3, G, G2, Lam
character*120 :: msg
character*8 :: charv(1)
integer :: intv(1)
real(8) :: realv(1)
! ------------------------------------------------------------------------- !
if (ndi /= 3) then
msg = 'this umat may only be used for elements &
&with three direct stress components'
call stdb_abqerr(-3, msg, intv, realv, charv)
end if
! elastic properties
K = props(1)
K3 = 3. * K
G = props(2)
G2 = 2. * G
Lam = (K3 - G2) / 3.
! elastic stiffness
ddsdde = 0.
do i=1,ndi
do j = 1,ndi
ddsdde(j,i) = Lam
end do
ddsdde(i,i) = G2 + Lam
end do
do i=ndi+1,ntens
ddsdde(i,i) = G
end do
! stress update
stress = stress + matmul(ddsdde, dstran)
return
end subroutine umat
Note The elastic material model is implemented in free-form Fortran. Matmodlab handles free-form Fortran seemlessly. In Abaqus, the user must inform the Abaqus build system that the material model is implemented in free-form Fortran by adding the
-free
(/free
on Windows) flag to thecompile_fortran
command in theirabaqus_v6.env
environment file.
Use the build-fext
executable to build the material model. The arguments for build-fext
are:
build-fext <name> <source files>
if name
is umat
, build-fext
will compile the subroutine against a library providing several Abaqus subroutines (sprind
, std_abqerr
, etc).
In [3]:
!../bin/build-fext umat umat_elastic.f90
In [4]:
from matmodlab2.umat import UMat
mps = MaterialPointSimulator('job')
K, G = 9.98004e9, 3.75094e9
mps.material = UMat([K, G])
In [5]:
mps.run_step('ESS', (.01,0,0))
Etrue = 9. * K * G / (3. * K + G)
Esim = mps.df['S.XX'].iloc[-1] / mps.df['E.XX'].iloc[-1]
assert abs(Etrue - Esim) / Etrue < 1e-6
In [6]:
mps = MaterialPointSimulator('job')
mps.material = UMat([K, G])
mps.run_step('E', (.01,0,0))
Htrue = K + 4. * G / 3.
Hsim = mps.df['S.XX'].iloc[-1] / mps.df['E.XX'].iloc[-1]
assert abs(Htrue - Hsim) / Htrue < 1e-6